package org.eclipseuseradmin.internal.ui.views;

import java.text.MessageFormat;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.security.auth.ILoginContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IPluginContribution;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.activities.ActivityManagerEvent;
import org.eclipse.ui.activities.IActivityManager;
import org.eclipse.ui.activities.IActivityManagerListener;
import org.eclipse.ui.activities.WorkbenchActivityHelper;
import org.eclipse.ui.part.ViewPart;
import org.eclipseuseradmin.internal.ui.UserAdminUiPlugin;
import org.eclipseuseradmin.internal.ui.editors.RoleElementInput;
import org.eclipseuseradmin.internal.ui.security.RolePrincipal;
import org.eclipseuseradmin.ui.BaseRoleElementAdapter;
import org.eclipseuseradmin.ui.IRoleElement;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdmin;

public class UserView extends ViewPart {

	private Composite mainComposite;

	private Composite loggedinComposite;

	private Composite loggedoutComposite;

	private Link loggedinLink;

	private Link loggedoutLink;

	private String userLogin;

	@Override
	public void createPartControl(Composite parent) {

		mainComposite = new Composite(parent, SWT.NONE);
		mainComposite.setLayout(new GridLayout());
		createOrRefreshControls(mainComposite);
		registerActivityListener();
	}

	private void createOrRefreshControls(Composite parent) {

		if (isAccountControlEnabled() && loggedinComposite == null) {
			createLoggedinControl(parent);
			if (loggedoutComposite != null) {
				loggedoutComposite.dispose();
				loggedoutComposite = null;
			}
			mainComposite.layout();
		} else if (!isAccountControlEnabled() && loggedoutComposite == null) {
			createLoggedoutControl(parent);
			if (loggedinComposite != null) {
				loggedinComposite.dispose();
				loggedinComposite = null;
			}
			mainComposite.layout();
		}
	}

	private void createLoggedinControl(Composite parent) {

		loggedinComposite = new Composite(parent, SWT.NONE);
		loggedinComposite.setLayout(new GridLayout());

		userLogin = getUserLogin();
		String loggedinLinkText = MessageFormat.format(
				ViewsMessages.get().UserView_loggedinLink, userLogin);

		loggedinLink = new Link(loggedinComposite, SWT.NONE);
		loggedinLink.setText(loggedinLinkText);
		loggedinLink.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				if ("account".equalsIgnoreCase(e.text)) {
					handelOpenEditor();
				} else if ("logout".equalsIgnoreCase(e.text)) {
					handelLogout();
				}
			}
		});
	}

	private void createLoggedoutControl(Composite parent) {

		loggedoutComposite = new Composite(parent, SWT.NONE);
		loggedoutComposite.setLayout(new GridLayout());

		loggedoutLink = new Link(loggedoutComposite, SWT.WRAP);
		loggedoutLink.setText(ViewsMessages.get().UserView_loggedoutLink);
		loggedoutLink.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if ("login".equalsIgnoreCase(e.text)) {
					handelLogin();
				}
			}
		});

	}

	private void handelOpenEditor() {

		if (userLogin == null) {
			return;
		}

		Role role = getUserAdmin().getRole(userLogin);
		if (role == null) {
			return;
		}

		IRoleElement roleElement = (IRoleElement) Platform.getAdapterManager()
				.getAdapter(role, IRoleElement.class);
		if (roleElement == null) {
			return;
		}

		IEditorDescriptor editorDescriptor = BaseRoleElementAdapter
				.getDefaultEditor(roleElement);
		if (editorDescriptor == null) {
			return;
		}

		try {
			PlatformUI.getWorkbench().getActiveWorkbenchWindow()
					.getActivePage().openEditor(
							new RoleElementInput(roleElement),
							editorDescriptor.getId());
		} catch (PartInitException e) {
			UserAdminUiPlugin.log(e);
		}
	}

	private void handelLogin() {

		try {
			getLoginContext().login();
		} catch (LoginException e) {
			// do nothing
		}
	}

	private void handelLogout() {

		try {
			getLoginContext().logout();
		} catch (LoginException e) {
			// do nothing
		}
	}

	private boolean isAccountControlEnabled() {

		return !WorkbenchActivityHelper.filterItem(new IPluginContribution() {
			public String getLocalId() {
				return "org.eclipseuseradmin.views.userView.loggedinControl";
			}

			public String getPluginId() {
				return UserAdminUiPlugin.PLUGIN_ID;
			}
		});
	}

	private void registerActivityListener() {

		getActivityManager().addActivityManagerListener(
				new IActivityManagerListener() {
					public void activityManagerChanged(
							ActivityManagerEvent activityManagerEvent) {
						if (activityManagerEvent
								.haveEnabledActivityIdsChanged())
							createOrRefreshControls(mainComposite);
					}
				});
	}

	@Override
	public void setFocus() {
		mainComposite.setFocus();
	}

	private ILoginContext getLoginContext() {
		return UserAdminUiPlugin.getLoginContext();
	}

	private UserAdmin getUserAdmin() {
		return UserAdminUiPlugin.getUserAdmin();
	}

	private IActivityManager getActivityManager() {
		return PlatformUI.getWorkbench().getActivitySupport()
				.getActivityManager();
	}

	private String getUserLogin() {

		try {
			Subject subject = getLoginContext().getLoginContext().getSubject();
			if (subject == null) {
				return null;
			}

			Set<RolePrincipal> rolePrincipals = subject
					.getPrincipals(RolePrincipal.class);
			if (rolePrincipals.isEmpty()) {
				return null;
			}

			for (RolePrincipal principal : rolePrincipals) {
				return principal.getName();
			}
			return null;
		} catch (LoginException e) {
			UserAdminUiPlugin.log(e);
			return null;
		}
	}

}
